/*
 * this part may contain codes of following projects:
 * 1. Anti Web HTTP(awhttp) server of Hardcore Software
 * 2. light httpd
 * 3. Null httpd
 *
 * copy right, the above authors or organzations
 */

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <errno.h>


#include "http.h"
#include "log.h"

#ifndef __DECONST
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#endif

#define isSpaces(ch) (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\b' || ch == '\f' || ch == '\n')

static int hexit(char c);


/* kill all left and right space of the given string 
   spend 3-8 seconds every 100,000,000 times */
char *
trim(char *src)
{
    int i = 0;
    char *begin = src;
    while(src[i] != '\0')
    {
        if(! isSpaces(src[i]))
        {
            break;
        }
        else
        {
            begin++;
        }
        i++;
    }
          
    for(i = strlen(src)-1; i >= 0;  i--)
    {
        if(! isSpaces(src[i]))
        {
            break;
        }
        else
        {
            src[i] = '\0';
        }
    }
    return begin;
}


/*
 * urldecode funciton
 * which is a part of Anti Web HTTP server of Hardcore Software
 *
 */
static int 
hexit(char c) 
{
    if ( c >= '0' && c <= '9' )
        return c - '0';
    if ( c >= 'a' && c <= 'f' )
        return c - 'a' + 10;
    if ( c >= 'A' && c <= 'F' )
        return c - 'A' + 10;
    return 0;
}


/* Decode string %xx -> char (in place) */
void 
urldecode(char *buf) 
{
    int v;
    char *p, *s, *w;

    w = buf;
    p = buf;
    while (*p) 
    {
        v=0;

        if (*p == '%') 
        {
            s = p;
            s++;

            if (isxdigit((int) s[0]) && isxdigit((int) s[1]) ) 
            {
                v=hexit(s[0])*16+hexit(s[1]);
                if (v)      /* do not decode %00 to null char */
                { 
                    *w=(char)v;
                    p=&s[1];
                }
            }
        }
        if (!v) 
        {
            *w=*p;
        }
        p++; 
        w++;
    }
    *w='\0';
    return;
}

/* swap the dest char to specific one */
void 
swapchar(char *string, char oldchar, char newchar)
{
	while (*string) 
	{
		if (*string == oldchar) *string = newchar;
		string++;
	}
}


/* get the header field value by key */
char *
get_header_field_value(HEADER_FIELD *header_field, char *key)
{
    unsigned int i;

    for (i = 0; i < MAX_HEADER_FIELDS; i++)
    {
        if (header_field[i].field_name == NULL)
        {
            continue;
        }
        else if (strncmp(header_field[i].field_name, key, strlen(key)) == 0)
        {
            return header_field[i].field_value;
        }
    }
    return NULL;
}

/* set the header field value with 'value' by key */
void
set_header_field_value(HEADER_FIELD *header_field_ptr, char *key, char *value)
{
    unsigned int i;

    for (i = 0; i < MAX_HEADER_FIELDS; i++)
    {
        if (strncmp(header_field_ptr[i].field_name, key, strlen(key)) == 0)
        {
            header_field_ptr[i].field_value = value;
            return;
        }
    }
    return;
}


/*
* Find the first occurrence of find in s, where the search is limited to the
* first slen characters of s.
*/
char *
bsd_strnstr(const char *s, const char *find, size_t slen)
{
	char c, sc;
	size_t len;

	if ((c = *find++) != '\0') {
		len = strlen(find);
		do {
			do {
				if (slen < 1 || (sc = *s) == '\0')
					return (NULL);
				--slen;
				++s;
			} while (sc != c);
			if (len > slen)
				return (NULL);
		} while (strncmp(s, find, len) != 0);
		s--;
	}
	return (__DECONST(char *, s));
}


